#include <sstream>
#include "Perimetro.h"

using namespace TP::Juego::Arena::Utilidades;

Perimetro::Perimetro() {
	_rol = new Rol(ROL_PERIMETRO, DESC_PERIMETRO);
	_vida = VIDA_PERIMETRO;
	this->_alto = 0;
	this->_ancho = 0;
	setEsEnemigo(true);
}

Perimetro::Perimetro(unsigned long int pAlto, unsigned long int pAncho) {
	_rol = new Rol(ROL_PERIMETRO, DESC_PERIMETRO);
	_vida = VIDA_PERIMETRO;
	this->_alto = pAlto;
	this->_ancho = pAncho;
	setEsEnemigo(true);
}

Perimetro::~Perimetro() { }

Utilidad* Perimetro::clonar() {
	Utilidad *copia = new Perimetro(_alto, _ancho);
	if (_posicion != NULL) {
		copia->setPosicion(_posicion->clonar());
	}
	return copia;
}

unsigned long int Perimetro::getAlto() {
	return this->_alto;
}

unsigned long int Perimetro::getAncho() {
	return this->_ancho;
}

bool Perimetro::pertenecePerimetro(Posicion* pPosicion) {
	bool pertenece = false;
	if (pPosicion) {
		pertenece = true;
		pertenece = pertenece && pPosicion->X() > 0;
		pertenece = pertenece && pPosicion->X() < this->getAncho() - 1;
		pertenece = pertenece && pPosicion->Y() > 0;
		pertenece = pertenece && pPosicion->Y() < this->getAlto() - 1;
	}
	return pertenece;
}

Vector2D* Perimetro::getNormalAPuntoPerimetro(Posicion* pPosicion) {
	// Por default, la posicion no corresponde a un punto del perimetro.
	// Por ende, no tiene una normal definida.
	Vector2D* normal = new Vector2D(0, 0);
	if (pPosicion->X() == 0) {
		normal->X(1);

		if (pPosicion->Y() == 0)
			normal->Y(1);

		else if (pPosicion->Y() == this->getAlto() - 1)
			normal->Y(-1);

		else
			normal->Y(0);
	}
	else if (pPosicion->X() == this->getAncho() - 1) {
		normal->X(-1);

		if (pPosicion->Y() == 0)
			normal->Y(1);

		else if (pPosicion->Y() == this->getAlto() - 1)
			normal->Y(-1);

		else
			normal->Y(0);
	}
	else if (pPosicion->Y() == 0) {
		normal->Y(1);

		if (pPosicion->X() == 0)
			normal->X(1);
		else if (pPosicion->X() == this->getAncho() - 1)
			normal->X(-1);
		else
			normal->X(0);
	}
	else if (pPosicion->Y() == this->getAlto() - 1) {
		normal->Y(-1);

		if (pPosicion->X() == 0)
			normal->X(1);
		else if (pPosicion->X() == this->getAncho() - 1)
			normal->X(-1);
		else
			normal->X(0);
	}
	return normal;
}

Vector2D* Perimetro::getPuntoAdjuntoInterior(Posicion* pPosicion) {
	Vector2D* interior = new Vector2D(0, 0);
	if (pPosicion->X() == 0) {
		interior->X(1);

		if (pPosicion->Y() == 0)
			interior->Y(1);

		else if (pPosicion->Y() == this->getAlto() - 1)
			interior->Y(-1);

		else
			interior->Y(pPosicion->Y());
	}
	else if (pPosicion->X() == this->getAncho() - 1) {
		interior->X(-1);

		if (pPosicion->Y() == 0)
			interior->Y(1);

		else if (pPosicion->Y() == this->getAlto() - 1)
			interior->Y(-1);

		else
			interior->Y(pPosicion->Y());
	}
	else if (pPosicion->Y() == 0) {
		interior->Y(1);

		if (pPosicion->X() == 0)
			interior->X(1);
		else if (pPosicion->X() == this->getAncho() - 1)
			interior->X(-1);
		else
			interior->X(pPosicion->X());
	}
	else if (pPosicion->Y() == this->getAlto() - 1) {
		interior->Y(-1);

		if (pPosicion->X() == 0)
			interior->X(1);
		else if (pPosicion->X() == this->getAncho() - 1)
			interior->X(-1);
		else
			interior->X(pPosicion->X());
	}
	return interior;
}

TiXmlElement* Perimetro::aElementoXML() {
	TiXmlElement * element = new TiXmlElement(_rol->Nombre().c_str());
	
	element->SetDoubleAttribute("vida", _vida);

	std::stringstream stream;
	stream << this->_alto;
	element->SetAttribute("alto", stream.str().c_str());

	std::stringstream streamAncho;
	streamAncho << this->_ancho;
	element->SetAttribute("ancho", streamAncho.str().c_str());

	return element;
}

void Perimetro::deElementoXML(TiXmlElement* pElemento) {
	if (pElemento->Value() == _rol->Nombre()) {
		// Hidrato los atributos de tipo nativo.
		pElemento->Attribute("vida", &_vida);

		std::stringstream streamAnchura;
		streamAnchura << pElemento->Attribute("ancho");
		streamAnchura >> this->_ancho;

		std::stringstream streamAltura;
		streamAltura << pElemento->Attribute("alto");
		streamAltura >> this->_alto;
	}
}

double Perimetro::getRadio() {
	return radio_perimetro;
}

int Perimetro::getPuntosDestruccion() {
	return PUNTAJE_PERIMETRO;
}